package sardine.tpd;


import com.google.common.base.Charsets;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpResponseStatus;
import sardine.route.RouteMatcherFactory;
import sardine.route.SimpleRouteMatcher;
import sardine.webserver.MatcherFilter;
import sardine.webserver.NotConsumedException;

import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_0;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

/**
 * Auth: bruce-sha
 * Date: 2015/3/6
 */
@ChannelHandler.Sharable
public class LBServerInboundHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

    final SimpleRouteMatcher router = RouteMatcherFactory.singleton();
    final MatcherFilter filter;
//    private static List<AbstractResourceHandler> staticResourceHandlers = null;

    public LBServerInboundHandler(MatcherFilter filter) {
        this.filter = filter;
    }

    //    private class HttpRequestWrapper extends HttpServletRequestWrapper {
//        private byte[] cachedBytes;
//
//        public HttpRequestWrapper(HttpServletRequest request) {
//            super(request);
//        }
//
//        @Override
//        public ServletInputStream getInputStream() throws IOException {
//            if (cachedBytes == null) {
//                cacheInputStream();
//            }
//            return new CachedServletInputStream();
//        }
//
//        private void cacheInputStream() throws IOException {
//            cachedBytes = IOUtils.toByteArray(super.getInputStream());
//        }
//
//        public class CachedServletInputStream extends ServletInputStream {
//            private ByteArrayInputStream byteArrayInputStream;
//
//            public CachedServletInputStream() {
//                byteArrayInputStream = new ByteArrayInputStream(cachedBytes);
//            }
//
//            @Override
//            public int read() {
//                return byteArrayInputStream.read();
//            }
//        }
//    }

    protected void messageReceived(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
//    public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        //先当作静态内容处理
//        HttpRequest request=(HttpRequest)msg;

//        HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(new DefaultHttpDataFactory(false), request);

        // bath static resources
//        if (staticResourceHandlers != null) {
//            for (AbstractResourceHandler staticResourceHandler : staticResourceHandlers) {
//                AbstractFileResolvingResource resource = staticResourceHandler.getResource(request);
//                if (resource != null && resource.isReadable()) {
//                    IOUtils.copy(resource.getInputStream(), response.getWriter());
//                    return;
//                }
//            }
//        }

//        try {
//            if (StaticResourceHanlder.handleResource(ctx, request)) return;
////            if (StaticResourceHanlder.handle2 (ctx, request))     return;
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

        final DefaultFullHttpResponse response = new DefaultFullHttpResponse(
                request.protocolVersion() == HTTP_1_0 ? HTTP_1_0 : HTTP_1_1, OK);

        // LOG.debug("jettyhandler, bath();");
        try {
            // build the request so 'getInputStream()' can be called multiple times
            filter.doFilter(request, response, ctx);
//            baseRequest.setHandled(true);
        } catch (NotConsumedException ignore) {

            try {
                if (!StaticResourceHanlder.handleResource(request, ctx)) {
                    // TODO : Not use an exception in order to be faster.
//            baseRequest.setHandled(false);
                    //TODO:注意这里有问题，到底先处理静态文件还是动态文件
                    response.setStatus(HttpResponseStatus.NOT_FOUND);
                    response.content().writeBytes(MatcherFilter.NOT_FOUND.getBytes(Charsets.UTF_8));
                    response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
                    ctx.writeAndFlush(response);
                }
//            if (StaticResourceHanlder.handle2 (ctx, request))     return;
            } catch (Exception e) {
                //ignore
            }


        }


//        if (false) {
//            String s = System.currentTimeMillis() + "<br>" + request.toString();
//            ByteBuf content = Unpooled.wrappedBuffer(s.getBytes(Charsets.UTF_8));
//            DefaultFullHttpResponse resp = new DefaultFullHttpResponse(HTTP_1_1, OK, content);
//            resp.headers().set(CONTENT_TYPE, "text/html;charset=UTF-8");
//            resp.headers().set(CONTENT_LENGTH, content.readableBytes());//must
//            ctx.writeAndFlush(resp);
//            return;
//        }

//        //先当作静态内容处理
//
//        try {
////            if(StaticHanlder.bath(ctx, request))       return;
//            if (StaticResourceHanlder.handleResource(ctx, request)) return;
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        final String uri = request.uri();
//        final QueryStringDecoder query = new QueryStringDecoder(uri);
//        io.netty.handler.codec.http.HttpMethod method = request.method();
//
//        final String path = query.path();
//        HttpMethod httpMethod = HttpMethod.valueOf(method.name().toString().toLowerCase());
//        String acceptType = request.headers().getAndConvert("accept");
//
//        RouteMatch routeMatch = router.findOneTargetForRequestedRoute(httpMethod, path, acceptType);
//
//
//
//        RouteImpl route = (RouteImpl) routeMatch.target();
//
//        //这里改了---
//        Request req = RequestResponseFactory.create(routeMatch, request);
//        Response rep = RequestResponseFactory.create(response);
//
//        Object result = null;
//
//        try {
//            result = route.bath(req, rep);
//        } catch (HaltException he) {
//
//            response.setStatus(new HttpResponseStatus(he.getStatusCode(), "reason"));
//            response.content().writeBytes(he.getBody().getBytes(Charsets.UTF_8));
//            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=UTF-8");
//            response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());//must
//
//            ctx.write(response);
//            ctx.flush();
//
//            return;
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        //这里改了 ---
//
////        {
////            // bath static resources
////            if (SparkFilter.staticResourceHandlers != null) {
////                for (AbstractResourceHandler staticResourceHandler : SparkFilter.staticResourceHandlers) {
////                    AbstractFileResolvingResource resource = staticResourceHandler.getResource(httpRequest);
////                    if (resource != null && resource.isReadable()) {
////                        IOUtils.copy(resource.getInputStream(), response.getWriter());
////                        return;
////                    }
////                }
////            }
////
////        }
//        String resultStr = route.render(result);
//
//        response.content().writeBytes(resultStr.getBytes(Charsets.UTF_8));
//
////        response.headers().set(CONTENT_TYPE, "text/html;charset=UTF-8");
////        response.headers().set(CONTENT_LENGTH, response.content().readableBytes());//must
//        response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=UTF-8");
//        response.headers().setInt(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());//must
//
//
//        ctx.write(response);
//        ctx.writeAndFlush(result);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
    }
}